package com.hxkj.client.service.http.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.hxkj.client.service.TemplteServiceClient;
import com.hxkj.client.service.http.VisualizationService;
import com.hxkj.client.service.taglib.config.WhitelistLabel;
import com.hxkj.domain.po.Templet;
import com.hxkj.domain.po.VisualBean;
import com.hxkj.utils.MD5Utils;
import com.platform.common.domain.result.ResultDataStruct;
import com.platform.common.domain.result.ResultMessageStruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/***
 * @author yaosy
 * @desc 可视化serviceimpl
 * @date 2018年8月15日
 * **/
@Service
@Slf4j
public class VisualizationServiceImpl implements VisualizationService {

    @Autowired
    private TemplteServiceClient templteServiceClient;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String INCLUDE = "_include";

    private static final String EXPLAIN_INCLUDE="<#include";

    private static final String EXPLAIN_SCRIPT="<@script";

    private static final String EXPLAIN_LINK="<@link";

    private static final String EXPLAIN_IMG="<@img";

    @Override
    public ResultMessageStruct replace(VisualBean visualBean) throws Exception {
        ResultMessageStruct resultMessageStruct = new ResultMessageStruct();
        try {
            String oldSource = visualBean.getContent();
            JSONObject jsonObject = JSONObject.parseObject(oldSource);

            //1)根据前端的uuid和数据库查询的uuid判断是否是一致;一致则允许修改;不一致则提示
            Templet templet = new Templet();
            templet.setTempletId(visualBean.getTemplteId());
            templet.setDelTag((byte) 0);
            templet.setSiteId(visualBean.getSiteId());
            ResultDataStruct resultDataStruct = templteServiceClient.get(templet);
            String templetString = JSON.toJSONString(resultDataStruct.getData());
            templet = (Templet) JSON.parseObject(templetString, new TypeReference<Templet>(){});
            if(!StringUtils.isEmpty(templet.getTempletAlias()) && !templet.getTempletAlias().equals(visualBean.getUuid())){
                resultMessageStruct.setCode(402);
                resultMessageStruct.setMessage("模板已变更,请关闭后重新打开!");
                return resultMessageStruct;
            }

            //2)读取模板文件;获取修改后标签所在位置
            //content示例:<@cms_breadcrumbs columnId=13 orderType=11 num=12></@cms_breadcrumbs>
            //获取自定义标签名;获取num值
            String source = templet.getSource();

            //Pattern pattern = Pattern.compile("<@"+visualBean.getTaglibName()+"[^>]+>");//匹配该模板包含该标签
            Pattern pattern = Pattern.compile("<@[^link][^script][^>]+>");//匹配该模板包含该标签
            Matcher matcher = pattern.matcher(source);

            //获取num
            int num = 0;
            int sum = 0;
            if(jsonObject != null)  num =  Integer.parseInt(jsonObject.get("num").toString());//5
            Pattern pattern1 =  Pattern.compile("<(S*#include?)[^>]*>.*?|<.html?/>");
            Matcher m1 = pattern1.matcher(source);
            int d = 0;
            String newTaglib = "";
            String finalContent = "";
            while(m1.find()){//统计当前模板中包含多少个include标签<可视化窗口中Include的标签是按顺序排列>
                d++;
            }
            if(num<=d){//说明此处修改的是Include标签
                int currentInclude = 1;
                String name = jsonObject.get("cur")==null?"":jsonObject.get("cur").toString();//对应include替换的标签
                pattern1 =  Pattern.compile("<(S*#include?)[^>]*>.*?|<.html?/>");
                m1 = pattern1.matcher(source);
                while(m1.find()){
                    if(num==currentInclude){
                        newTaglib = m1.group();
                        finalContent = newTaglib;
                        Map<String, String> params = JSONObject.parseObject(jsonObject.toJSONString(), new TypeReference<Map<String, String>>(){});
                        for (Map.Entry<String, String> entry : params.entrySet()) {
                            String key = entry.getKey();
                            if(!key.equals("cur")) continue;
                            String value = entry.getValue();
                            //newTaglib = newTaglib.replaceAll(key+"=.+\\s+", key+"='"+value+"' ");
                            //此处无参数处理;只能通过拼接和截取来组装数据
                            Pattern p2 = Pattern.compile("tabs=['|\"].+['|\"]{0}>$");//
                            Matcher m2 = p2.matcher(newTaglib);
                            while(m2.find()){
                                String tabName = m2.group();
                                newTaglib = newTaglib.replace(tabName, "");
                                newTaglib = newTaglib.substring(0,EXPLAIN_INCLUDE.length());
                                newTaglib = newTaglib+" \""+value+"\" "+tabName;
                            }
                        }
                    }
                    currentInclude++;
                }
            }else{
                int number = 1;
                int count = num -d;
                source = readConent(source,count,jsonObject,number);
            }
            if(num<=d) {
                if(StringUtils.isEmpty(newTaglib)){
                    resultMessageStruct.setCode(402);
                    resultMessageStruct.setMessage("无替换模板!");
                    return resultMessageStruct;
                }
                source = source.replace(finalContent, newTaglib); //处理Include标签
            }
            templet.setSource(source);
            templet.setTempletAlias(MD5Utils.getMd5ByTemplte());
            templteServiceClient.modify(templet);
            resultMessageStruct.setCode(200);
            resultMessageStruct.setMessage("操作成功!");

        }catch(Exception e){
            e.printStackTrace();
            resultMessageStruct.setCode(402);
            resultMessageStruct.setMessage("操作失败!"+e.getMessage()+","+e.getCause());
        }
        return resultMessageStruct;
    }

    public String readConent(String source , int count , JSONObject jsonObject,int number){
        if(StringUtils.isEmpty(source)) return source;
        InputStream in = null;
        BufferedReader reader = null;
        StringBuffer sb = new StringBuffer();
        try{
            in =  IOUtils.toInputStream(source,"UTF-8");
            reader = new BufferedReader(
                    new InputStreamReader(in));
            String readData = null;
            while((readData = reader.readLine()) != null){
                String readerLine = readData;
                if(StringUtils.isEmpty(readerLine)){
                    sb.append(readerLine).append(System.getProperty("line.separator"));
                    continue;
                }
                if(readerLine.indexOf(EXPLAIN_SCRIPT) != -1 || readerLine.indexOf(EXPLAIN_IMG) != -1
                        || readerLine.indexOf(EXPLAIN_SCRIPT) != -1 || (readerLine.indexOf("$")!=-1 && readerLine.indexOf("<@") != -1)||readerLine.indexOf(EXPLAIN_INCLUDE) != -1) {
                    sb.append(readerLine).append(System.getProperty("line.separator"));
                    continue;
                }else{
                    if(readerLine.indexOf("<@") != -1){
                        //标签白名单处理
                        Pattern whiteParttern = Pattern.compile("<@(\\S+)\\s+");
                        Matcher whiteMatter = whiteParttern.matcher(readerLine);
                        String tagName= "";
                        while(whiteMatter.find()){
                            tagName = whiteMatter.group(1);
                        }
                        if(WhitelistLabel.getWhiteMaps().containsKey(tagName)){
                            sb.append(readerLine);
                            continue;
                        }
                        if(number == count){
                            log.error("可替换的模板为{}",readerLine);
                            Map<String, String> params = JSONObject.parseObject(jsonObject.toJSONString(), new TypeReference<Map<String, String>>(){});
                            for (Map.Entry<String, String> entry : params.entrySet()) {
                                String key = entry.getKey();
                                if(key.equals("num")) continue;
                                String value = entry.getValue();
                                readerLine = readerLine.replaceAll(key+"\\s{0,1}=.+?\\s+", key+"='"+value+"' ");
                            }
                            sb.append(readerLine).append(System.getProperty("line.separator"));
                            log.error("替换后的模板为{}",readerLine);
                        }else{
                            sb.append(readerLine).append(System.getProperty("line.separator"));
                        }
                        number++;
                    }else{
                        sb.append(readerLine).append(System.getProperty("line.separator"));
                    }

                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (in != null) in.close();
                if (reader != null) reader.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}
